package com.motorhome.h5.service.impl;

import com.motorhome.base.pay.weixin.WxSignUtil;
import com.motorhome.base.pay.weixin.WxXmlUtil;
import com.motorhome.base.util.*;
import com.motorhome.h5.common.statics.H5Statics;
import com.motorhome.h5.dao.HomeDao;
import com.motorhome.h5.domain.*;
import com.motorhome.h5.service.HomeService;
import com.motorhome.h5.service.OpenService;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: John
 */
@Service
public class HomeServiceImpl implements HomeService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private HomeDao homeDao;

    @Autowired
    private OpenService openService;

    @Override
    public List<Car> getAllCarList(Map<String, Object> params) {

        List<Car> carList = homeDao.getAllCarList();

        //过滤已被预定车辆
        List<Order> orderList = homeDao.getOrderListByStatus(0);
        if (orderList != null && !orderList.isEmpty()) {
            try {
                Date startDate = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(params.get("startDate").toString());
                Date endDate = new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(params.get("endDate").toString());
                for (Order order : orderList) {
                    Date orderStartDate = order.getStartDate();
                    Date orderEndDate = order.getEndDate();
                    if (filterCar(startDate, endDate, orderStartDate, orderEndDate)) {
                        Iterator<Car> iterator = carList.iterator();
                        while (iterator.hasNext()) {
                            Car car = iterator.next();
                            if (car.getId().equals(order.getCarId())) {
                                iterator.remove();
                            }
                        }
                    }
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

        //设置价格
        List<Price> priceList = homeDao.getAllPriceList();
        if (carList != null && priceList != null) {
            //设置车辆价格
            carList.forEach(car -> car.setPrices(
                    priceList.stream()
                            .filter(price -> price.getCarId().equals(car.getId()))
                            .collect(Collectors.toList())));
            //按价格排序
            Collections.sort(carList);
        }

        return carList;
    }

    private boolean filterCar(Date startDate, Date endDate, Date orderStartDate, Date orderEndDate) {
        if (orderEndDate.before(startDate) || orderEndDate.getTime() == startDate.getTime()) {
            return false;
        }
        if (orderStartDate.after(endDate) || orderStartDate.getTime() == endDate.getTime()) {
            return false;
        }
        return true;
    }

    @Override
    public Result insertOrder(HttpServletRequest request, User loginUser, String startCityId, String startCityName,
                              String startShopId, String startShopName, String startDate,
                              String endCityId, String endCityName, String endShopId, String endShopName,
                              String endDate, String carId, String carName, String carDescription,
                              String price, String days, String total, String totalSnapshot) {

        //判断车型是否预定完
        Car car = homeDao.getCarById(Long.parseLong(carId));
        if (car.getCarNum() < 1) {
            return new Result(2, "此车型车辆已被预定完，您可以选择其他车型");
        }

        //租车日期格式化
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date start = null, end = null;
        try {
            start = dateFormat.parse(startDate);
            end = dateFormat.parse(endDate);
        } catch (ParseException e) {
            logger.error("日期转换异常", e);
        }

        //是否使用优惠券
        boolean useCoupon = false;
        String couponGuid = (String)request.getAttribute("couponGuid");
        String guid = (String)request.getAttribute("guid");
        String subCount = (String)request.getAttribute("subCount");
        String couponValue = (String)request.getAttribute("couponValue");
        String typeName = (String)request.getAttribute("typeName");
        if (!"0".equals(couponGuid)) {
            useCoupon = true;
        }

        //优惠券抵扣金额计算
        Float totalFloat = Float.parseFloat(total);//待支付总金额
        if (useCoupon) {
            if ("代金券".equals(typeName)) {
                Float couponValueJE = Float.parseFloat(couponValue);
                totalFloat = totalFloat - couponValueJE;
                totalSnapshot = totalSnapshot + "-代金券" + couponValueJE;
            } else if ("折扣券".equals(typeName)) {
                float couponValueZK = Float.parseFloat(couponValue);
                totalFloat = totalFloat * couponValueZK;
                totalSnapshot = totalSnapshot + "*折扣券" + couponValueZK;
            } else if ("普通券".equals(typeName)) {
                Float couponValueJE = Float.parseFloat(couponValue);
                totalFloat = totalFloat - couponValueJE;
                totalSnapshot = totalSnapshot + "-普通券" + couponValueJE;
            }
        }

        //车上人员责任
        String bx1 = (String)request.getAttribute("bx1");
        if (!"0".equals(bx1)) {
            Float bx1Float = Float.parseFloat(bx1) * Integer.parseInt(days);
            totalFloat = totalFloat + bx1Float;
            totalSnapshot = totalSnapshot + "+车上人员责任" + bx1 + "*天数" + days;
        }

        //不计免赔
        String bx2 = (String)request.getAttribute("bx2");
        if (!"0".equals(bx2)) {
            Float bx2Float = Float.parseFloat(bx2) * Integer.parseInt(days);
            totalFloat = totalFloat + bx2Float;
            totalSnapshot = totalSnapshot + "+不计免赔" + bx2 + "*天数" + days;
        }

        //判断用户储值余额
        String payType = (String)request.getAttribute("payType");
        if ("1".equals(payType)) {
            boolean enable = false;
            try {
                String memberInfoJson = openService.getMemberInfo(loginUser.getCardId());
                if (StringUtil.isNotBlank(memberInfoJson)) {
                    OpenGetMemberResult openGetMemberResult = JsonUtil.fromJson(memberInfoJson, OpenGetMemberResult.class);
                    if (openGetMemberResult != null && openGetMemberResult.getStatus() == 0) {
                        List<OpenMember> openMembers = openGetMemberResult.getData();
                        if (openMembers != null && !openMembers.isEmpty()) {
                            OpenMember openMember = openMembers.get(0);
                            String enableValue = openMember.getEnableValue();
                            if (StringUtil.isNotBlank(enableValue) && Float.parseFloat(enableValue) >= totalFloat) {
                                enable = true;
                            }
                        }
                    }
                }
            } catch (Exception e) {
                logger.error("查询储值余额失败", e);
            }
            if (!enable) {
                return new Result(98, "储值余额不足");
            }
        }

        //核销优惠券
        if (useCoupon) {
            boolean subSuccess = false;
            String couponError = "优惠券核销失败";
            try {
                //优惠券核销成功后扣除费用
                String result = openService.subCoupon(guid, subCount, null);
                if (StringUtil.isNotBlank(result)) {
                    Map map = JsonUtil.fromJson(result, Map.class);
                    if (map != null && Integer.parseInt(map.get("status").toString()) == 0) {
                        subSuccess = true;
                    } else {
                        couponError = map.get("message").toString();
                    }
                }
            } catch (Exception e) {
                logger.error("优惠券核销失败", e);
            }

            //核销失败，返回提示
            if (!subSuccess) {
                return new Result(3, couponError);
            }
        }

        //追加优惠券抵扣快照
        totalSnapshot += "=" + totalFloat + "元";

        //插入订单
        homeDao.insertOrder(loginUser.getId(), loginUser.getPhone(), loginUser.getUserName(),
                Long.parseLong(startCityId), startCityName, Long.parseLong(startShopId), startShopName,
                start, Long.parseLong(endCityId), endCityName, Long.parseLong(endShopId), endShopName, end,
                Long.parseLong(carId), carName, carDescription,
                Float.parseFloat(price), Integer.parseInt(days), totalFloat,
                totalSnapshot,
                couponGuid, guid, subCount, couponValue, typeName);
        Long orderId = homeDao.queryMysqlLastAutoId();

        //在线支付
        if ("1".equals(payType)) {//储值支付
            String consumeResultJson = openService.consume(loginUser.getCardId(), totalFloat, totalFloat, totalFloat, 0f, 0f, 0f, 0f);
            if (StringUtil.isNotBlank(consumeResultJson)) {
                Map consumeResult = JsonUtil.fromJson(consumeResultJson, Map.class);
                if (consumeResult != null && Integer.parseInt(consumeResult.get("status").toString()) == 0) {
                    homeDao.updateOrderPayStatusSuccess(2, orderId, consumeResultJson);
                    return new Result(100, "储值支付成功");
                }
            }
            return new Result(99, "储值支付失败");

        } else {//微信支付
            Map<String, Object> payData = new HashMap<>();
            payData.put("payOrderNo", orderId);
            payData.put("payOrderMoney", totalFloat);
            payData.put("payOrderSubject", "慢生活房车" + carName);
            payData.put("openId", loginUser.getOpenId());
            return new Result(0, "跳转微信公众号支付", payData);
        }
    }

    @Override
    public Price getPriceByCarId(long carId) {
        return homeDao.getPriceByCarId(carId);
    }

    @Override
    public Car getCarById(long carId) {
        return homeDao.getCarById(carId);
    }

    @Override
    public void tenPay(HttpServletRequest request, Model model) {

        //商户订单号、订单金额、订单标题、openId
        String payOrderNo = request.getParameter("payOrderNo");
        String payOrderMoney = request.getParameter("payOrderMoney");
        String payOrderSubject = request.getParameter("payOrderSubject");
        String openId = request.getParameter("openId");

        //测试
//        payOrderMoney = "0.01";

        //金额转换成单位分
        payOrderMoney = new BigDecimal(payOrderMoney).multiply(new BigDecimal("100")).intValue() + "";
        logger.info("payOrderMoney=" + payOrderMoney);

        try {
            //下单
            String spbillCreateIp = IpUtil.getIpAddress(request);
            if (StringUtil.isBlank(spbillCreateIp)) {
                spbillCreateIp = "116.62.224.156";
            } else {
                spbillCreateIp = spbillCreateIp.split(",")[0];
            }
            Map<String, String> wxparams = new HashMap<>();
            wxparams.put("appid", H5Statics.MP_APPID);
            wxparams.put("mch_id", H5Statics.MP_PAY_MCH_ID);
            wxparams.put("nonce_str", RandomUtil.randomChars(32));
            wxparams.put("body", payOrderSubject);
            wxparams.put("out_trade_no", payOrderNo);
            wxparams.put("total_fee", payOrderMoney);
            wxparams.put("spbill_create_ip", spbillCreateIp);
            wxparams.put("notify_url", H5Statics.MP_PAY_NOTIFY_URL);
            wxparams.put("trade_type", "JSAPI");
            wxparams.put("openid", openId);
            wxparams.put("sign", WxSignUtil.getSign(wxparams, H5Statics.MP_PAY_APIKEY));
            String responseStr = new HttpClientUtil().post(H5Statics.MP_PAY_UNIFIEDORDER_URL, WxXmlUtil.getXml(wxparams));

//            logger.info("微信统一下单响应内容：" + new String(responseStr.getBytes("ISO-8859-1"), "UTF-8"));

            Map<String, String> wxResponseMap = new HashMap<>();
            Document document = DocumentHelper.parseText(responseStr);
            Iterator iterator = document.getRootElement().elementIterator();
            while (iterator.hasNext()) {
                Element element = (Element)iterator.next();
                wxResponseMap.put(element.getName(), element.getText());
            }

            if ("SUCCESS".equals(wxResponseMap.get("return_code"))
                    && "SUCCESS".equals(wxResponseMap.get("result_code"))) {

                Map<String, String> payParam = new HashMap<>();
                payParam.put("appId", wxResponseMap.get("appid"));
                payParam.put("timeStamp", System.currentTimeMillis() / 1000 + "");
                payParam.put("nonceStr", RandomUtil.randomChars(32));
                payParam.put("package", "prepay_id=" + wxResponseMap.get("prepay_id"));
                payParam.put("signType", "MD5");
                payParam.put("paySign", WxSignUtil.getSign(payParam, H5Statics.MP_PAY_APIKEY));
                payParam.put("_package", payParam.get("package")); //微信用了Java保留关键字，转换一下不然页面JSTL报错
                model.addAllAttributes(payParam);
            }

        } catch (Exception e) {
            logger.error("微信统一下单异常", e);
        }

    }

    @Override
    public String tenpayNotify(HttpServletRequest request, String resultXml) {
        logger.info("微信异步通知内容：" + resultXml);

        Map<String, String> responseResult = new HashMap<>();
        try {

            //获取参数
            Map<String, String> wxResponseMap = new HashMap<>();
            Document document = DocumentHelper.parseText(resultXml);
            Iterator iterator = document.getRootElement().elementIterator();
            while (iterator.hasNext()) {
                Element element = (Element)iterator.next();
                wxResponseMap.put(element.getName(), element.getText());
            }

            //校验签名
            final String sign = wxResponseMap.get("sign");
            wxResponseMap.remove("sign");
            String sign2 = WxSignUtil.getSign(wxResponseMap, H5Statics.MP_PAY_APIKEY);
            logger.info("微信返回签名：sign=" + sign);
            logger.info("验证生成签名：sign2=" + sign2);
            if (!sign.equals(sign2)) {
                responseResult.put("return_code", "FAIL");
                responseResult.put("return_msg", "通知校验失败");
                return WxXmlUtil.getXml(responseResult);
            }

            //处理业务
            String returnCode = wxResponseMap.get("return_code");
            if ("SUCCESS".equals(returnCode)) {

                String resultCode = wxResponseMap.get("result_code");
                if ("SUCCESS".equals(resultCode)) {

                    String out_trade_no = wxResponseMap.get("out_trade_no");
                    String transaction_id = wxResponseMap.get("transaction_id");
                    String total_fee = wxResponseMap.get("total_fee");

                    //更新订单支付结果
                    int row = homeDao.updateOrderPayStatusSuccess(0, Long.parseLong(out_trade_no), resultXml);
                    if (row > 0) {
                        responseResult.put("return_code", "SUCCESS");
                        responseResult.put("return_msg", "OK");
                        return WxXmlUtil.getXml(responseResult);
                    }
                }
            }

        } catch (Exception e) {
            logger.error("微信支付异步通知处理异常", e);
        }
        responseResult.put("return_code", "FAIL");
        responseResult.put("return_msg", "通知处理失败");
        return WxXmlUtil.getXml(responseResult);
    }
}
